/**
 * @fileOverview Cube.Element 类
 * @author <a href="mailto:simonsliu@tencent.com">simonsliu</a>
 * @date 11-11-16 - 下午12:17
 */
(function(window, Cube, undefined) {
    var ArrayProto = Array.prototype,
        slice = ArrayProto.slice;
    
	/**
	 * @class
	 */
Cube.define('Cube.Element',{
    constructor: function( selector, context ) {
        var // A simple way to check for HTML strings or ID strings
            // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
            quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
            rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
            match, ret, doc, elements;

        // Handle $(DOMElement)
        if ( selector.nodeType ) {
            this.context = this[0] = selector;
            this.length = 1;
            return this;
        }

        match = selector.match(quickExpr);
        doc = (context ? context.ownerDocument || context : document);

        if ( match && ( match[1] || !context )) {
            if ( match[1] ) {
                ret = rsingleTag.exec( selector );
                if ( ret ) {
                    this[0] = doc.createElement( ret[1] );
                }
            } else {
                this[0] = doc.getElementById( match[2] );
            }
            this.length = 1;
        } else {
            elements = slice.call(doc.querySelectorAll( selector ));
            elements.forEach(function(item,i){
                this[i]=item;
            }.bind(this));
            this.length = elements.length;
        }
        this.context = doc;
        return this;
	},
    /**
     * 添加类名
     * @param {String} className 类名
     */
    addClass: function addClass(className) {
        return this.each(function(i, elem){
           elem.classList.add(Cube.String.trim(className));
        });
    },
    removeClass: function removeClass(className) {
        return this.each(function(i, elem) {
            elem.classList.remove(Cube.String.trim(className));
        });
    },
    hasClass: function hasClass(className) {
        return this[0].classList.contains(Cube.String.trim(className));
    },
    toggleClass: function toggleClass(className) {
        className = Cube.String.trim(className);
        if (this.hasClass(className)) {
            return this.removeClass(className);
        } else {
            return this.addClass(className);
        }
    },
    /**
     * 设置/获取元素属性
     * @param {String|PlainObject} attrName 属性名称|属性键值对对象
     * @param {String} [attrValue] 属性值
     * @return {Cube.Element|*} 若为赋值操作，返回对象本身；若为取值操作，返回所取得的值
     */
    attr: function attr(attrName, attrValue) {
        var trim = Cube.String.trim;
        if (Cube.isPlainObject(attrName)) {
            return this.each(function(i, elem){
                Cube.each(attrName, function(name, value){
                   elem.setAttribute(name, trim(value));
                });
            });
        } else if (Cube.isString(attrName = trim(attrName))){
            if ( attrValue ) {
                return this.each(function(i, elem) {
                   elem.setAttribute(attrName, attrValue);
                });
            } else {
                return this[0].getAttribute(attrName);
            }
        }
    },
    removeAttr: function(attrName) {
        if(!Cube.isString(attrName)) {
            throw new TypeError('the type of arguments[0] <attrName> should be string, actually is ' + Cube.type(arguments[0]));
        }
        return this.each(function(i, elem) {
            elem.removeAttribute(Cube.String.trim(attrName));
        });
    },
    /**
     * 设置/获取元素样式，获取样式为元素运行时样式
     * @param {String|PlainObject} cssName 样式属性名称或属性－值键值对对象
     * @param {String} [cssValue] 样式值
     * @return {Cube.Element|String} 设值操作返回对象本身；取值操作返回所取的值
     */
    css: function css(cssName, cssValue) {
        var trim = Cube.String.trim;
        if (Cube.isPlainObject(cssName)) {
            return this.each(function(i,elem) {
                Cube.each(cssName, function(name, value) {
                   elem.style[name] = trim(value);
                });
            });
        } else if (Cube.isString(cssName = trim(cssName))){
            if ( cssValue ) {
                return this.each(function(i, elem) {
                   elem.style[cssName] = cssValue;
                });
            } else {
                return window.getComputedStyle(this[0])[cssName];
            }
        }
    },
    /**
     * 设置/获取元素内的html字符串
     * @param {String} html 将要设置的html字符串
     * @return {Cube.Element|String} 设值操作返回对象本身，取值操作返回所取得值
     */
    html: function html(html) {
        if (html) {
            return this.each(function(i, elem){
                elem.innerHTML = String(html);
            });
        }
        return this[0].innerHTML;
    },
    /**
     *
     * @param text
     */
    text: function text(text) {
        if (text) {
            return this.each(function(i, elem){
                elem.innerText = String(text);
            });
        }
        return this[0].innerText;
    },
    offset: function() {

    },
    position: function() {

    },
    scrollPosition: function() {

    },
    appendTo: function( parent ) {
        if ( parent ) {
            this.each(function( index, element ) {
                if ( parent.nodeType && parent.nodeType === 1 ) {
                    parent.appendChild( element );
                };
                if ( parent.$className && parent.$className === 'Cube.Element' ) {
                    parent.append( element );
                }
            });
        }
        return this;
    },
    append: function( child ) {
        if ( child ) {
            this.each(function( index, element ) {
                if ( child.nodeType && child.nodeType === 1 ) {
                    element.appendChild( child );
                };
                if ( child.$className && child.$className === 'Cube.Element' ) {
                    child.appendTo( element );
                }
            });
        }
        return this;
    },
    insertBefore: function() {

    },
    insertAfter: function() {

    },
    /**
     * 绑定事件
     * @param {String} type 事件类型
     * @param {Function} handler 事件回调函数
     * @param {Boolean} useCapture 是否使用捕获
     */
    bind: function(type, handler, useCapture) {
        return this.each(function(i, elem) {
            elem.addEventListener(type, handler, useCapture);
        });
    },
    /**
     *
     * @param type
     * @param handler
     * @param useCapture
     */
    one: function(type, handler, useCapture) {
        return this.each(function(i, elem) {
            elem.addEventListener(type, function(){
                this.removeEventListener(type);
                return handler.apply(this, arguments);
            }, useCapture);
        });
    },
    /**
     *
     * @param type
     * @param handler
     * @param useCapture
     */
    unbind: function(type, handler, useCapture) {
        return this.each(function(i, elem) {
            elem.removeEventListener(type, handler, useCapture);
        });
    },
    /**
     * 遍历对象
     * @param {Function} callback 回调函数
     * @param {PlainObject} args 参数
     */
    each: function( callback, args ) {
        return Cube.each( this, callback, args );
    }
});
})(window, Cube);